home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Apple II Magazines (PO)
/
Nibble Volume 10, No. 02 (1989-02)(MicroSPARC)(Side A)[a].zip
/
Nibble Volume 10, No. 02 (1989-02)(MicroSPARC)(Side A)[a].po
/
SHAPE.LIB.B.S
< prev
next >
Wrap
Text File
|
1996-12-24
|
31KB
|
1,213 lines
********************************
* *
* PARTB *
* Machine Language Routines *
* for Table.Librarian *
* by James Brodsky *
* *
* Copyright (c) 1987 *
* By Microsparc, Inc. *
* *
* Merlin Pro Assembler *
* *
********************************
*------------------------------------
* Zero page memory locations:
*------------------------------------
PTR2 EQU 0 ;general purpose pointer
SHAPE1 EQU 2 ;pointer to main table
END1 EQU 4 ;end of main table
EFLG EQU 6 ;set if [ESC] pressed
MAX EQU 7 ;max string len for input
PTR EQU 6 ;general use temporary pointer
PTR1 EQU 8 ;general use temporary pointer
CH EQU $24 ;40 column H cursor
CV EQU $25 ;V tab position
A1L EQU $3C
A1H EQU $3D
A2L EQU $3E
A2H EQU $3F
A4L EQU $42
A4H EQU $43
LINNUM EQU $50
TXTTAB EQU $67
LOMEM EQU $69
ARYTAB EQU $6B
STREND EQU $6D
HIGHDS EQU $94
HIGHTR EQU $96
LOWTR EQU $9B
DSCTMP EQU $9D
PRGEND EQU $AF
ERRFLG EQU $D8
SHAPE EQU $E8 ;pointer to shape table
*------------------------------------
* Hardware addresses:
*------------------------------------
BUFFER EQU $200
AMPV EQU $3F5
*------------------------------------
* BASIC and MONITOR routines:
*------------------------------------
CHRGET EQU $B1
CHRGOT EQU $B7
MOVEUP EQU $D39A
GDBUFS EQU $D539
FRMNUM EQU $DD67
CHKSTR EQU $DD6C
CHKCOM EQU $DEBE
SYNCHR EQU $DEC0
SYNERR EQU $DEC9
PTRGET EQU $DFE3
STRSPA EQU $E3DD
MOVSTR EQU $E5E2
GETBYT EQU $E6F8
GETADR EQU $E752
CLREOL EQU $FC9C
RDKEY EQU $FD0C
COUT EQU $FDED
COUT1 EQU $FDF0
MOVE EQU $FE2C
ORG $4000
*--------------------------------------------
*
* The following code is run once at $4000
* to embed the ML routines into the main
* Applesoft program.
* The code between INSTALL and PGMSTART
* is then abandoned.
*
*--------------------------------------------
INSTALL ;embed code into Applesoft
LDY #0
LDA PRGEND+1
LDX PRGEND
STA A4H
STX A4L
LDA #>END
LDX #<END
STA A2H
STX A2L
LDA #>PGMSTART
LDX #<PGMSTART
STA A1H
STX A1L
JSR MOVE
CLC
LDA #<END-PGMSTART
ADC PRGEND
STA PRGEND
STA LOMEM
STA ARYTAB
STA STREND
LDA #>END-PGMSTART
ADC PRGEND+1
STA PRGEND+1
STA LOMEM+1
STA ARYTAB+1
STA STREND+1
JMP $3D0
*-------------------------------------------------
*
* The following section of code is run once
* each time the Applesoft program is loaded.
* It moves the embedded ML routines to start
* at $C03 and restores the Applesoft
* end-of-program pointers to the end of the
* Applesoft code.
* The area where the ML routines were embedded
* can then be used by Applesoft for
* variable storage.
* NOTE that if the Applesoft program is stopped
* and saved after this section has been run,
* the ML routines will no longer be saved
* with it.
*
*-------------------------------------------------
PGMSTART LDY #0 ;move code to page $C
LDA PRGEND
STA A2L
SEC
SBC #<END-SEGMENT
STA A1L
LDA PRGEND+1
STA A2H
SBC #>END-SEGMENT
STA A1H
SEC
LDA PRGEND
SBC #<END-PGMSTART
STA PRGEND
STA LOMEM
STA ARYTAB
STA STREND
LDA PRGEND+1
SBC #>END-PGMSTART
STA PRGEND+1
STA LOMEM+1
STA ARYTAB+1
STA STREND+1
LDA #<VAREND
LDX #>VAREND
STA A4L
STX A4H
JSR MOVE ;use monitor to move code
SETAMPV LDY #1 ;save old amper vector
:1 LDA AMPV+1,Y
STA STASH,Y
DEY
BPL :1
LDA #>START ;setup our amper vector
LDY #<START
STA AMPV+2
STY AMPV+1
LDA #$4C
STA AMPV
RTS ;return to BASIC after setup
*----------------------------------------------------
* Program variable storage area:
*----------------------------------------------------
DUM $C03
STASH DS 2 ;save old amper vector here
MODE DS 1
STASH1 DS 2 ;[ESC] msg... WARNING -
; STASH1 actually extends
; over 20 bytes and overwrites
; remaining variables in this
; section.
ADRSAVE1 DS 2 ;start address of shape
ADREND1 DS 2 ;end address of shape
LENGTH1 DS 2 ;length of shape
ADRSAVE2 DS 2 ;start address of shape to move
ADREND2 DS 2 ;end address of shape to move
LENGTH2 DS 2 ;length of shape to move
FROMNUM DS 1 ;number ofshape to move
TONUM DS 1 ;number of location to move to
SHAPES DS 1 ;number shapes in table
COUNTER DS 1
TEMP DS 3
VAREND DEND
*---------------------------------------------------
*
* Start of ML code which was embedded in
* Applesoft program and has been moved to its
* running location.
* First routine saves old Ampersand vector and
* points Ampersand vector to the main
* entry point, START, then exits to BASIC.
*
*---------------------------------------------------
SEGMENT
ORG VAREND
*=================================================
* Entry to program - called by & vector:
* Determine which routine is called and
* jump to it.
*=================================================
START
PHA
JSR CHRGET ;advance TXTPTR
PLA
CMP #$80 ;END token
BNE NOTEND
* EXIT (restore old ampersand vector and pointers)
EXIT LDY #1
:1 LDA STASH,Y
STA AMPV+1,Y
DEY
BPL :1
LDA #8 ;set start of BASIC to $801
STA TXTTAB+1
LDA #0
STA TXTTAB
STA ERRFLG ;kill ONERR
LDY #2
:2 STA (TXTTAB),Y ;zero out first line
DEY
BPL :2
INC TXTTAB
RTS ;end restore machine
* Branch to routine called by BASIC:
NOTEND
CMP #$E3 ;LEN token
BEQ GETLEN
CMP #$A8 ;STORE token
BNE :1
JMP STORE
:1 CMP #$84 ;INPUT token
BNE :2
JMP STRINGS
:2 CMP #$83 ;DATA token
BNE :3
JMP DATA
:3 CMP #$85 ;DEL token
BNE :4
JMP DEL
:4 CMP #$D4 ;ABS token
BNE :5
JMP STRIP
:5 CMP #$D6 ;FRE token
BNE :6
JMP MEMORY
:6
JMP MEMMOV ;if not one of the above,
; see if it's "MOVE"
*---------------------------------------------------------
* GETLEN (Get start and end address of a shape)
* Called directly from BASIC for extract-a-shape function.
* Also used by ML add and delete routines
*
* & LEN shapenum
* returns: shape start address at PEEK (6)
* shape end address at PEEK (8)
*---------------------------------------------------------
GETLEN JSR GETBYT ;get number of shape to find
GETLEN1 TXA ;enter here from add or delete
LDX #0
ASL ;double shape # for index
STA PTR1
BCC :1
INX
:1 STX PTR1+1 ;move index into PTR1
CLC
LDA SHAPE ;move start address of offset to
ADC PTR1 ; desired shape into PTR
STA PTR
LDA SHAPE+1
ADC PTR1+1
STA PTR+1
CLC
LDY #0
LDA (PTR),Y ;move start address of desired
ADC SHAPE ; shape into PTR1 and into PTR
STA PTR1
TAX
INY ;Y = 1
LDA (PTR),Y
ADC SHAPE+1
STA PTR1+1
STA PTR+1
STX PTR
DEY ;Y = 0
:LOOP LDA (PTR1),Y ;scan through data until
BEQ :END ; zero byte found
INC PTR1
BNE :LOOP
INC PTR1+1
BNE :LOOP ;always
:END LDY #3
:2 LDA PTR,Y
STA ADRSAVE1,Y
DEY
BPL :2
SEC ;put lngth of shape into LENGTH1
LDA PTR1
SBC PTR
STA LENGTH1
LDA PTR1+1
SBC PTR+1
STA LENGTH1+1
INC LENGTH1
BNE :3
INC LENGTH1+1
:3 RTS ;end find LEN of shape
*--------------------------------------------------------
* STORE (add one shape to main table from aux table):
*
* & STORE shapenum AT END (add a shape)
* or
* & STORE shapenum AT shapenum (insert a shape)
*
* returns: PEEK (6) = 0 if successful
* PEEK (6) = 1 if memory conflice
*--------------------------------------------------------
STORE JSR GETBYT ;get number of shape to move
STX FROMNUM ;save shape number
JSR GETLEN1 ;get address & length of shape
JSR MOVPTRS ;move to ADRSAVE2, etc.
LDA #$C5 ;check for AT token
JSR SYNCHR
JSR SWITCH ;switch pointers for GETLEN
JSR OURADR ;get params of where to add
JSR UNSWITCH ;restore table pointers
* Check whether there's room to add shape:
CLC
LDA END1 ;add length of shape to
ADC LENGTH2 ; end address of table
PHA
LDA END1+1
ADC LENGTH2+1
STA PTR+1
PLA ;compare proposed new end addr
CMP SHAPE ; with start addr of aux table
LDA PTR+1
SBC SHAPE+1
BCC :OK ;continue if no collision
LDA #1
STA EFLG ;else set error flag and
RTS ; return without doing
:OK LDA SHAPE1 ;new shape table address =
STA PTR1 ; old address minus 2
SEC
SBC #2 ;move new table index address
STA SHAPE1 ; into SHAPE1
STA PTR ; and into PTR
LDA SHAPE1+1
STA PTR1+1 ;old index address into PTR1
SBC #0
STA SHAPE1+1
STA PTR+1
LDY #0
STY A1H
LDA (PTR1),Y
CLC
ADC #1 ;add 1 shape to number of
STA (SHAPE1),Y ; shapes in table index
STA SHAPES
INY
LDA (PTR1),Y ;move second byte of index
STA (SHAPE1),Y ; down 2 addresses
INY ;Y = 2
STY A1L
LDX TONUM
:OFFSET CLC
LDA (PTR1),Y ;get shape address offset
ADC A1L ;increase for new shape added
STA (PTR),Y ;store it 2 bytes lower in index
INY ;Y = 3
LDA (PTR1),Y
ADC A1H
STA (PTR),Y
DEY ;Y = 2
JSR INCPTRS
JSR INCPTRS
DEX
BNE :OFFSET
BIT MODE ;ADD or INSERT?
BPL :INSERT
* Make new offset if shape is added at end of table:
CLC
LDA LENGTH1
ADC #2
STA A1L
LDA LENGTH1+1
ADC #0
STA A1H
LDX #1
BNE :LOOP ;branch always
* Fix offsets if shape is inserted:
:INSERT SEC
LDA SHAPES
SBC TONUM
TAX
CLC
LDA #2
ADC LENGTH2
STA A1L
LDA #0
ADC LENGTH2+1
STA A1H
:LOOP CLC
LDA (PTR),Y
ADC A1L
STA (PTR),Y
INY
LDA (PTR),Y
ADC A1H
STA (PTR),Y
DEY
JSR INCPTR
JSR INCPTR
DEX
BNE :LOOP
BIT MODE ;ADD or INSERT?
BMI :ADDEND
* Open up space to insert shape:
CLC
LDA ADRSAVE1
STA LOWTR ;start of block to move
ADC LENGTH2
STA A4L ;destination address
LDA ADRSAVE1+1
STA LOWTR+1
ADC LENGTH2+1
STA A4H
LDA END1 ;end of block to move
LDY END1+1
STA HIGHTR
INC HIGHTR
BNE :2
INY
:2 STY HIGHTR+1
JSR HIGHER ;go move part of table
* Move new shape into main table:
LDA ADRSAVE1 ;destination address
LDY ADRSAVE1+1
BNE :4 ;always
:ADDEND LDX ADREND1 ;dest addr for add at end
LDY ADREND1+1
INX
BNE :3
INY
:3 TXA
:4 STA A4L
STY A4H
LDA ADRSAVE2 ;start address
LDY ADRSAVE2+1
STA A1L
STY A1H
LDA ADREND2 ;end address
LDY ADREND2+1
STA A2L
STY A2H
LDY #0
JSR MOVE
:UPDATE CLC ;update end of table address
LDA LENGTH2
ADC END1
STA END1
LDA LENGTH2+1
ADC END1+1
STA END1+1
LDA #0
STA EFLG ;clear error flag
STOREND RTS ;end add one entry
*---------------------------------------
* SUBROUTINES (used by STORE and DEL):
*---------------------------------------
SWITCH LDX #1
:1 LDA SHAPE,X ;move main shape table address
STA TEMP,X ; into SHAPE for GETLEN routine
LDA SHAPE1,X
STA SHAPE,X
DEX
BPL :1
RTS
UNSWITCH LDX #1
:1 LDA TEMP,X
STA SHAPE,X
DEX
BPL :1
RTS
MOVPTRS LDX #5 ;save address & length
:1 LDA ADRSAVE1,X
STA ADRSAVE2,X
DEX
BPL :1
RTS
OURADR LDY #0
LDA (SHAPE1),Y
STA SHAPES ;number shapes in main table
STY MODE
JSR CHRGOT ;get loc of shape to add or DEL
CMP #$80 ;END token ?
BNE :1 ;no, go get a shape number
STA MODE ;yes, set MODE for end (A = $80)
INC MODE
JSR CHRGET ;advance TXTPTR and
LDA SHAPES ; use number of shapes in table
TAX
BNE :2
LDA END1 ;use END1 if starting new table
LDY END1+1
STA ADRSAVE1
STA ADREND1
STY ADRSAVE1+1
STY ADREND1+1
LDY #0
STY LENGTH1
STY LENGTH1+1
RTS
:1 JSR GETBYT
:2 STX TONUM ;place to move shape to or from
JMP GETLEN1 ;get move-to address and RTS
INCPTRS
INC PTR1
BNE INCPTR
INC PTR1+1
INCPTR INC PTR
BNE :1
INC PTR+1
:1 RTS
*---------------------------------------------------------
* DEL (Delete one shape):
*
* & DEL shapenum
*---------------------------------------------------------
DEL JSR SWITCH ;move main table adr into SHAPE
JSR OURADR ;get info on shape to DEL
JSR MOVPTRS ;save it at ADRSAVE2, etc.
* Get length of segment to delete:
LDX TONUM ;get info on next higher shape
CPX SHAPES ; or end of table
BNE :1A ;branch if not at end
DEC MODE ;else set MODE negative
SEC ;and use end of table info
LDA END1
SBC ADRSAVE2
STA LENGTH1
LDA END1+1
SBC ADRSAVE2+1
STA LENGTH1+1
CLC
BCC :1B
:1A INX ;point at next higher shape
JSR GETLEN1 ;get info on next higher shape
SEC ;calculate length to delete
LDA ADRSAVE1
SBC ADRSAVE2
STA LENGTH1
LDA ADRSAVE1+1
SBC ADRSAVE2+1
STA LENGTH1+1
:1B JSR UNSWITCH ;restore SHAPE pointer
* Get address of index to last shape:
LDX #0
LDA SHAPES
ASL ;double # of shapes for index
BCC :1
INX
:1 CLC
ADC SHAPE1
STA PTR
TXA
ADC SHAPE1+1
STA PTR+1
SEC ;(PTR1) = (PTR - 2)
LDA PTR
SBC #2
STA PTR1
LDA PTR+1
SBC #0
STA PTR1+1
* Calculate offset for shape deleted if not at END:
LDY #0 ;subtract start of this shape
CLC ; from start of next shape
LDA LENGTH1
ADC #2
STA A1L
LDA LENGTH1+1
ADC #0
STA A1H
LDA SHAPES
BIT MODE ;delete from END ?
BMI :3 ;yes
SEC ;calculate # of shapes above
SBC TONUM ;shape to be deleted
TAX ;# of shapes above into X
DEX
BEQ :3A ;branch if next to last
* Decrement all indices above deleted shape:
:LOOP SEC
LDA (PTR),Y ;get original offset
SBC A1L ;subtract for deleted shape
STA (PTR),Y ;put back in same place
INY ;then do the hi byte
LDA (PTR),Y
SBC A1H
STA (PTR),Y
DEY
JSR DECPTRS
JSR DECPTRS
DEX
BNE :LOOP ;loop if not finished
* Fix offsets for shapes below deleted shape
* (Subtract #2 from each offset and move each
* offset up one position in table):
:3A INC TONUM
:3 LDX TONUM
DEX
:LOOP1 SEC
LDA (PTR1),Y
SBC #2
STA (PTR),Y
INY
LDA (PTR1),Y
SBC #0
STA (PTR),Y
DEY
JSR DECPTRS
JSR DECPTRS
DEX
BNE :LOOP1 ;loop until finished
BIT MODE
BMI :DECNUM ;branch if DEL at END
* Move block of table down if shape deleted from middle:
LDA ADRSAVE2 ;move-to address
LDY ADRSAVE2+1
STA A4L
STY A4H
LDA ADRSAVE1 ;start of block to move
LDY ADRSAVE1+1
STA A1L
STY A1H
LDA END1 ;end of block to move
LDY END1+1
STA A2L
STY A2H
LDY #0
JSR MOVE ;use monitor move routine
* Decrement number of shapes:
:DECNUM DEC SHAPES
LDA SHAPES
STA (PTR),Y ;poke new # into table header
INY
LDA (PTR1),Y ;move next byte intact-sometimes
STA (PTR),Y ; used as a type indicator
* Decrease length of table:
SEC
LDA END1
SBC LENGTH1
STA END1
LDA END1+1
SBC LENGTH1+1
STA END1+1
* Fix start address of table:
CLC
LDA SHAPE1
ADC #2
STA SHAPE1
LDA SHAPE1+1
ADC #0
STA SHAPE1+1
RTS ;end DEL one shape
*-------------------------------
* SUBROUTINES (Used by DEL):
*-------------------------------
DECPTRS LDA PTR1
BNE :1
DEC PTR1+1
:1 DEC PTR1
DECPTR LDA PTR
BNE :1
DEC PTR+1
:1 DEC PTR
RTS
*---------------------------------------------------------
* MEMORY (find how many shapes fit below hi-res page):
* Enter with start address of table in $E8,E9
* end address of table in $8,9
* & FRE
* returns: PEEK(6) = number of shapes that
* will fit below $4000
*---------------------------------------------------------
MEMORY
:1 LDA #$40 ;check at $4000
STA PTR2+1
LDY #0
STY PTR2
LDA (SHAPE),Y ;get number of shapes
STA TONUM ;and save it
LDA SHAPE ;move start address of table
LDX SHAPE+1 ; into PTR
STA PTR
STX PTR+1
LDX #0 ;use X as a counter
:LOOP JSR INCPTR ;point at next shape offset
JSR INCPTR
CLC
LDA (PTR),Y ;calculate address of
ADC SHAPE ; next shape in table
STA PTR2
INY
LDA (PTR),Y
ADC SHAPE+1
DEY
CMP PTR2+1 ;has hi byte reached limit?
BLT :2 ;no, increment & continue
BGE :3 ;yes, exit
:2 INX
CPX TONUM ;reached last shape ?
BLT :LOOP ;no, back thru loop
LDA PTR1+1 ;check end of table
CMP PTR2+1 ; for collision
BGE :3 ;last shape doesn't fit
INX
:3 DEX ;we've gone one too far
STX EFLG ;mark intact valid shape
RTS ;and return to caller
*---------------------------------------------------------
* Jump to monitor move routine (to move down)
* or to BASIC BLTU routine (to move up)
* SYNTAX:
* & MOVE,[old start adr],[old end adr] TO [new start adr]
*---------------------------------------------------------
MEMMOV EQU *
CMP #'M
BEQ :1
JMP SYNERR
:1 LDA #'O
JSR SYNCHR
LDA #'V
JSR SYNCHR
LDA #'E
JSR SYNCHR
JSR CHKCOM
JSR FRMNUM ;get start address
JSR GETADR
:A LDA LINNUM ;LINNUM has old start address
STA A1L ;store it for move down
PHA ;push it for move up
LDA LINNUM+1
STA A1H
PHA
*
JSR CHKCOM ;next parameter -
JSR FRMNUM ; get end address of range
JSR GETADR
:B LDA LINNUM
STA A2L
PHA
LDA LINNUM+1
STA A2H
PHA
*
LDA #$C1 ;check for "TO" token
JSR SYNCHR
JSR FRMNUM ;get destination address
JSR GETADR
LDA LINNUM
STA A4L
LDA LINNUM+1
STA A4H
*
PLA ;recover old end address
STA HIGHTR+1 ; store it for MOVEUP
PLA
STA HIGHTR
INC HIGHTR
BNE :2
INC HIGHTR+1
:2 PLA ;recover old start address
STA LOWTR+1 ; store it for MOVEUP
PLA
STA LOWTR
* Decide whether move up or down:
CMP LINNUM
LDA LOWTR+1
SBC LINNUM+1
BCS LOWER
* Move up in memory:
HIGHER SEC ;get length of segment
LDA HIGHTR ; to move
SBC LOWTR
TAY
LDA HIGHTR+1
SBC LOWTR+1
TAX
TYA ;low byte -> A
CLC ;add length to destination addr
ADC A4L
STA HIGHDS
TXA
ADC A4H
STA HIGHDS+1
JMP MOVEUP
* Move down in memory:
LOWER LDY #0
JMP MOVE ;monitor memory move
*----------------------------------------------------
* & DATA:
* Determine whether a table is a shape table
* or a vector table.
* Return with PEEK (6) = 1 if vector
* = 0 if shape
* Assumption: a vector shape (with no index) will
* not have two or more non-consecutive zero bytes
*----------------------------------------------------
DATA
LDY #0
STY COUNTER
STY MODE
STY EFLG ;PEEK(6) = 0
:LOOP LDA (PTR1),Y ;get next byte
BEQ :INCCTR ;branch if it's zero
BIT MODE ;non-zero following zero ?
BPL :LOOP1 ;no, continue
INC MODE ;yes, clear MODE and continue
:LOOP1 INC PTR1
BNE :1
INC PTR1+1
:1 LDA PTR1+1 ;check for end of table
CMP PTR2+1
BLT :LOOP
LDA PTR1
CMP PTR2
BLT :LOOP
BEQ :LOOP
INC EFLG ;PEEK(6) = 1 if vector table
RTS ;exit to caller
:INCCTR BIT MODE ;was preceding byte also 0 ?
BMI :LOOP1 ;yes
DEC MODE ;set MODE = #$FF
INC COUNTER
LDA COUNTER
CMP #2
BLT :LOOP1
RTS ;PEEK(6) = 0 if shape table
;exit to caller
*------------------------------------------------
* STRIP filename routine:
* & ABS sexpr1,sexpr2
* returns "pure" filename in sexpr2, less
* any ProDOS prefix or slot/drive parameter
*------------------------------------------------
STRIP JSR PTRGET ;get name of first string
STA PTR1
STY PTR1+1
LDY #0
LDA (PTR1),Y ;get length of string
STA LENGTH1
TAX
INY
LDA (PTR1),Y ;get address of string
STA PTR
STA A1L
INY
LDA (PTR1),Y
STA PTR+1
STA A1H
LDY #0
STY COUNTER
:LOOP LDA (PTR),Y ;get next char of string
JSR INCPTR
CMP #'/ ;is it a slash?
BNE :CHKCOM
STX LENGTH1
DEC LENGTH1
LDA PTR
STA A1L
LDA PTR+1
STA A1H
CLC
BCC :1 ;branch always
:CHKCOM CMP #', ;is it a comma ?
BNE :1
STX LENGTH2
SEC
LDA LENGTH1
SBC LENGTH2
TAX
CLC
BCC :END
:1 DEX
BNE :LOOP
LDX LENGTH1
:END
STX LENGTH2
LDA #$0D ;RETURN
STA BUFFER,X
DEX
LDY #0
:LUP LDA (A1L),Y
STA BUFFER,Y
INY
DEX
CPX #$FF
BNE :LUP
JSR CHKCOM ;read a comma
JSR PTRGET ;get adr of second variable
LDX LENGTH2
JMP EXIT1
*------------------------------------------------------
* STRING input routine:
* & INPUT sexpr [,aexpr]
* optional second parameter limits length of input.
* if length is defined, routine also writes
* them on text page 2
* returns: string input in sexpr
* PEEK(6) = 1 if user pressed [ESC] else =0
* [DELETE] key works like backspace
*------------------------------------------------------
STRINGS JSR PTRGET ;get name of variable
JSR CHKSTR ;make sure it's a string
LDY #0
STY MODE
LDX #19 ;store pgm's [ESC] prompt
:1B LDA $7D7,X
STA STASH1,X
DEX
BPL :1B
LDA #$FE
STA MAX ;default max input length
JSR CHRGOT ;end of input params?
BEQ :1 ;yes, branch
JSR CHKCOM
JSR GETBYT ;get max allowable length
INX
STX MAX
DEC MODE ;MODE = #$FF
LDA #$60
STA $B72
:1 LDX #$00 ;zero X reg
STX EFLG ;zero ESC flag
JSR RDKEY ;get first char input
CMP #$8D ;[RETURN] ?
BEQ :ADDINP ;yes, process it
PHA ;else save it
JSR CLREOL ;and clear line on screen
PLA
JMP :INPUT1
*
:NOTCR JSR COUT ;print character
BIT MODE
BPL :1A
STA $B72,X ;print also on page 2
CPX MAX
BGE :1A
LDA #$60 ;flashing space
STA $B73,X ; as a cursor on page 2
:1A INX
CPX MAX ;buffer full?
BLT :INPUT ;no, go get more input
:BCKSPC TXA ;full buffer or back arrow key
BEQ :INPUT ;branch if at beginning
JSR ERASE ;erase one character
BNE :INPUT ;branch if not at beginning
JSR FIXPRMPT ;else restore [ESC] prompt
:INPUT JSR RDKEY
:INPUT1 CMP #$9B ;[ESC] ?
BNE :4 ;no, continue
CPX #0 ;at beginning of input?
BEQ :3 ;yes, set flag and return
JSR FIXPRMPT ;no, restore [ESC] message and
:2 JSR ERASE ; erase to beginning of input
BNE :2
BEQ :INPUT
:3 INC EFLG ;set ESC flag and
BNE :CR ; return to BASIC
:4 CMP #$88 ;[<--]
BEQ :BCKSPC
CMP #$FF ;[DELETE]
BEQ :BCKSPC
CMP #$8D ;[RETURN]
BEQ :ADDINP
CMP #$A0 ;reject CONTROL characters
BLT :INPUT
CPX #0
BNE :ADDINP
JSR OURPRMPT ;display [ESC] message
:ADDINP STA BUFFER,X
CMP #$8D
BNE :NOTCR
:CR LDA #$8D
JSR COUT
:EXIT LDY EFLG ;DON'T CHANGE STRING
BEQ EXIT1 ; IF EXITING VIA [ESC]
RTS
EXIT1 LDY #$00
TXA
STA ($83),Y
STA $1E
INY
LDA #$00
STA ($83),Y
INY
LDA #$02
STA ($83),Y
JSR GDBUFS
LDA $1E
JSR STRSPA
LDY #$02
:LOOP LDA DSCTMP,Y
STA ($83),Y
DEY
BPL :LOOP
LDX #$00
LDY #$02
LDA DSCTMP
JMP MOVSTR
ERASE LDA #$88
JSR COUT1
LDA #$A0 ;print " ";
JSR COUT1
BIT MODE
BPL :6
STA $B72,X
LDA #$60
STA $B71,X
:6 LDA #$88
JSR COUT1
DEX
RTS ;end erase one char
OURPRMPT LDY #20 ;print "ERASE ENTRY"
PHA ;save entered char
:LOOP LDA PRMPT,Y
STA $7D7,Y
STA $BD7,Y
DEY
BPL :LOOP
PLA
RTS
FIXPRMPT LDY #19 ;restore pgm's [ESC] prompt
PHA
:LOOP LDA STASH1,Y
STA $7D7,Y
STA $BD7,Y
DEY
BPL :LOOP
PLA
RTS
PRMPT ASC "ERASE ENTRY"
ASC " " ;10 spaces
HEX 000000
ORG
END